#include "Adapter.h"

#include <QSerialPortInfo>

#include <QDebug>


#define STATUS_WaitHeader           0x00000000
#define STATUS_WaitData             0x00000001
#define STATUS_WaitDataOrEnd        0x00000002

#define FRAME_HEADER      0x99
#define FRAME_END         0xfd





Adapter::Adapter(QObject *parent) : QObject(parent)
{
    m_status  = STATUS_WaitHeader;    
}

Adapter::~Adapter()
{
    if(m_port.isOpen())   {
        m_port.close();
    }
}

void Adapter::init(const QString &portName)
{
    qDebug() << "Port name" << portName;

    m_port.setPortName(portName);
    m_port.setBaudRate(QSerialPort::Baud9600);
    m_port.setParity(QSerialPort::NoParity);
    m_port.setDataBits(QSerialPort::Data8);
    m_port.setStopBits(QSerialPort::OneStop);
    m_port.setFlowControl(QSerialPort::NoFlowControl);


    if(m_port.open(QIODevice::ReadWrite)){

        connect(&m_port, SIGNAL(readyRead()), this, SLOT(readDeviceData()));

        qDebug() << "串口打开成功";
    }
    else{
        qDebug() << "串口" << m_port.portName() << "打开失败" << m_port.errorString();
    }
}



void Adapter::readBraceletSn(quint32 playerMask){
    quint8 buf[6];
    buf[0]  = 0x07;
    buf[1]  = 0xc0;
    buf[2]  = 0x02;
    buf[3]  = 0x00;

    switch(playerMask){
    case Player_1:
        buf[4]  = 0x01;
        break;
    case Player_2:
        buf[4]  = 0x02;
        break;
    case Player_3:
        buf[4]  = 0x03;
        break;
    }

    buf[5]  = 0x00;

    sendPackage(buf, sizeof(buf));
}


void Adapter::startToCompete(){
    quint8 buf[6];
    buf[0]  = 0x07;
    buf[1]  = 0xc0;
    buf[2]  = 0x00;
    buf[3]  = 0x00;
    buf[4]  = 0x03;
    buf[5]  = 0x00;

    sendPackage(buf, sizeof(buf));
}



void Adapter::reset(){
    quint8 buf[6];
    buf[0]  = 0x07;
    buf[1]  = 0xcc;
    buf[2]  = 0xcc;
    buf[3]  = 0xcc;
    buf[4]  = 0xcc;
    buf[5]  = 0xcc;

    sendPackage(buf, sizeof(buf));
}


void Adapter::readDeviceData()
{
    quint8 buf[20];
    qint64 bytes  = m_port.bytesAvailable();
    if(bytes <= sizeof(buf)){
        m_port.read((char*)buf, 20);
        for(qint64 i = 0; i < bytes; i++){
            ingestByte(buf[i]);
        }
    }
    else{
        m_port.clear();
    }
}

void Adapter::ingestByte(quint8 data)
{
    switch(m_status){
        case STATUS_WaitHeader:
        if( FRAME_HEADER == data){
            m_status  = STATUS_WaitData;
            qDebug() << "found frame header";
        }
        break;

    case STATUS_WaitData:
        if(FRAME_END == data){
            m_status  = STATUS_WaitHeader;
        }
        else if(FRAME_HEADER != data){
            m_status  = STATUS_WaitDataOrEnd;
            m_cache.append(data);
        }
        break;

    case STATUS_WaitDataOrEnd:
        if(FRAME_END == data){
            // 一帧结束
            parse();
            m_cache.clear();
            m_status  = STATUS_WaitHeader;
        }
        else if(FRAME_HEADER != data){

            m_cache.append(data);
        }
        else{
            m_cache.clear();
            m_status  = STATUS_WaitDataOrEnd;
        }
        break;
    }
}


void Adapter::parse()
{

    qDebug() << "Frame read" << m_cache;
    if(4 == m_cache.length()){
        quint8 playerIdByte  = m_cache.at(1);
        quint8 actionByte  = m_cache.at(2);
        if( 0x01 <= playerIdByte  &&  0x03 >= playerIdByte ){
            switch (actionByte) {
            case 0x41:
                emit selectionCommit(mapPlayerMask(playerIdByte), 1);//选择选项A
                break;
            case 0x42:
                emit selectionCommit(mapPlayerMask(playerIdByte), 2);//选择选项B
                break;
            case 0x43:
                emit selectionCommit(mapPlayerMask(playerIdByte), 3);//选择选项C
                break;
            case 0x44:
                emit selectionCommit(mapPlayerMask(playerIdByte), 4);//选择选项D
                break;
            case 0x4f:
                emit competationCommit(mapPlayerMask(playerIdByte));//抢答
                break;
            default:
                qDebug() << "Unknown action code:" << actionByte;
                break;
            }
        }
        else{
            qDebug() << "Unused raw player id";
        }
    }
    else if(10 == m_cache.length()){
        QByteArray  arr;
        for(int i = 0; i < 10; i++){
            arr.append(m_cache.at(i));
        }

        qDebug() << "手环码" << arr;
        emit braceletReady(0x00, arr);
    }
}

void Adapter::sendPackage(quint8 *buf, quint64 length)
{
    QByteArray data;
    data.append(FRAME_HEADER);
    for(int i = 0; i < length; i++){
        data.append(buf[i]);
    }
    data.append(FRAME_END);
    data.append('\r');
    data.append('\n');

    qDebug() << "Port output" << data;
    m_port.write(data);
}

quint32 Adapter::mapPlayerMask(quint8 rawId)
{
    switch(rawId){
    case 0x01:
        return Player_1;
    case 0x02:
        return Player_2;
    case 0x03:
        return Player_3;
    }
}
